package com.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@Slf4j
public class IpHashLoadBalancer implements ReactorServiceInstanceLoadBalancer {
	public String serviceId;
    public ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

    public IpHashLoadBalancer(
            ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
            String serviceId) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
    }

	@Override
	public Mono<Response<ServiceInstance>> choose(@SuppressWarnings("rawtypes") Request request) {
		if (serviceInstanceListSupplierProvider != null) {
            ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
                    .getIfAvailable(NoopServiceInstanceListSupplier::new);
            
            supplier.get().next();
            return supplier.get().next().map((instances) -> getInstanceResponse(request, instances));
        }
        return null;
	}
	
	/**
	 * 
	 * 方法描述：通过hash_ip决定返回的可用服务，测试时发现参数instances列表是无序的，需要排序处理
	 * @param request
	 * @param instances
	 * @return
	 */
	private Response<ServiceInstance> getInstanceResponse(
            @SuppressWarnings("rawtypes") Request request,
            List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            return new EmptyResponse();
        }
        //排序
        instances =  sort(instances);
		RequestDataContext context = (RequestDataContext) request.getContext();
		log.info("{}",context.toString());
		String jsessionid = (String) context.getClientRequest().getCookies().getFirst("JSESSIONID");
		int hash = Math.abs(jsessionid.hashCode());
        int pos = hash % instances.size();

        ServiceInstance instance = instances.get(pos);
        return new DefaultResponse(instance);
    }
	
	/**
	 * 
	 * 方法描述：可用服务排序
	 * @param list
	 * @return
	 */
	public List<ServiceInstance> sort(List<ServiceInstance>  list){
		
		Collections.sort(list, new Comparator<ServiceInstance>() {
			 //排序
             @Override
			public int compare(ServiceInstance o1, ServiceInstance o2) {
            	String s1 = o1.getHost()+o1.getPort();
            	String s2 = o2.getHost()+o2.getPort();
				return s1.compareTo(s2);
			 }
	    });
		
		return list;
	}
	
	
	
	
	

}
